<template>
  <div
    class="editContainer"
    @dragenter.prevent="onDragenter"
    @dragover.prevent
    @dragleave.prevent="onDragleave"
    @drop.prevent="onDrop"
  >
    <div
      class="mindMapContainer"
      ref="mindMapContainer"
      id="mindMapContainer"
    ></div>
     <Count :mindMap="mindMap" v-if="!isZenMode"></Count>
    <Navigator v-if="mindMap" :mindMap="mindMap"></Navigator>
    <NavigatorToolbar :mindMap="mindMap" v-if="!isZenMode"></NavigatorToolbar>
    <OutlineSidebar :mindMap="mindMap"></OutlineSidebar>
    <Style v-if="mindMap && !isZenMode" :mindMap="mindMap"></Style>
    <BaseStyle
      :data="mindMapData"
      :configData="mindMapConfig"
      :mindMap="mindMap"
    ></BaseStyle>
    <AssociativeLineStyle
      v-if="mindMap"
      :mindMap="mindMap"
    ></AssociativeLineStyle>
    <Theme v-if="mindMap" :data="mindMapData" :mindMap="mindMap"></Theme>
    <Structure :mindMap="mindMap"></Structure>
    <ShortcutKey></ShortcutKey>
    <Contextmenu v-if="mindMap" :mindMap="mindMap"></Contextmenu>
    <RichTextToolbar v-if="mindMap" :mindMap="mindMap"></RichTextToolbar>
    <NodeNoteContentShow
      v-if="mindMap"
      :mindMap="mindMap"
    ></NodeNoteContentShow>
    <NodeImgPreview v-if="mindMap" :mindMap="mindMap"></NodeImgPreview>
    <SidebarTrigger v-if="!isZenMode"></SidebarTrigger>
    <Search v-if="mindMap" :mindMap="mindMap"></Search>
    <NodeIconSidebar v-if="mindMap" :mindMap="mindMap"></NodeIconSidebar>
    <NodeIconToolbar v-if="mindMap" :mindMap="mindMap"></NodeIconToolbar>
    <OutlineEdit v-if="mindMap" :mindMap="mindMap"></OutlineEdit>
    <Scrollbar v-if="isShowScrollbar && mindMap" :mindMap="mindMap"></Scrollbar>
    <FormulaSidebar v-if="mindMap" :mindMap="mindMap"></FormulaSidebar>
    <NodeOuterFrame v-if="mindMap" :mindMap="mindMap"></NodeOuterFrame>
    <NodeTagStyle v-if="mindMap" :mindMap="mindMap"></NodeTagStyle>
    <Setting :configData="mindMapConfig" :mindMap="mindMap"></Setting>
    <NodeImgPlacementToolbar
      v-if="mindMap"
      :mindMap="mindMap"
    ></NodeImgPlacementToolbar>
    <NodeNoteSidebar v-if="mindMap" :mindMap="mindMap"></NodeNoteSidebar>
    <NodeFile v-if="mindMap" :mindMap="mindMap"></NodeFile>
    <div
      class="dragMask"
      v-if="showDragMask"
      @dragleave.stop.prevent="onDragleave"
      @dragover.stop.prevent
      @drop.stop.prevent="onDrop"
    >
      <div class="dragTip">{{ $t('edit.dragTip') }}</div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { ElMessage, ElNotification, ElMessageBox, ElLoading } from 'element-plus'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/stores'
import { useEventBus } from '@/hooks'
import MindMap from 'simple-mind-map'
import { getData as getApiData, storeData, getConfig } from '@/api'
import exampleData from 'simple-mind-map/example/exampleData'
import { showLoading, hideLoading } from '@/utils/loading'
import icon from '@/config/icon'
import handleClipboardText from '@/utils/handleClipboardText'

import OutlineSidebar from './OutlineSidebar.vue'
import Style from './Style.vue'
import BaseStyle from './BaseStyle.vue'
import Theme from './Theme.vue'
import Structure from './Structure.vue'
import Count from './Count.vue'
import NavigatorToolbar from './NavigatorToolbar.vue'
import ShortcutKey from './ShortcutKey.vue'
import Contextmenu from './Contextmenu.vue'
import RichTextToolbar from './RichTextToolbar.vue'
import NodeNoteContentShow from './NodeNoteContentShow.vue'
import Navigator from './Navigator.vue'
import NodeImgPreview from './NodeImgPreview.vue'
import SidebarTrigger from './SidebarTrigger.vue'
import Search from './Search.vue'
import NodeIconSidebar from './NodeIconSidebar.vue'
import NodeIconToolbar from './NodeIconToolbar.vue'
import OutlineEdit from './OutlineEdit.vue' 
import Scrollbar from './Scrollbar.vue'
import FormulaSidebar from './FormulaSidebar.vue'
import NodeOuterFrame from './NodeOuterFrame.vue'
import NodeTagStyle from './NodeTagStyle.vue'
import Setting from './Setting.vue'
import AssociativeLineStyle from './AssociativeLineStyle.vue'
import NodeImgPlacementToolbar from './NodeImgPlacementToolbar.vue'
import NodeNoteSidebar from './NodeNoteSidebar.vue'
import NodeFile from './NodeFile.vue'

// 注册插件
import RichText from 'simple-mind-map/src/plugins/RichText.js'
import ScrollbarPlugin from 'simple-mind-map/src/plugins/Scrollbar.js'
// 组合式API设置
const route = useRoute()
const { t } = useI18n()
const { $on, $off, $emit, $once } = useEventBus()
const store = useMainStore()

// 从store获取响应式状态
const { localConfig, activeSidebar, extraTextOnExport, isDragOutlineTreeNode } = storeToRefs(store)

// 从 localConfig 中获取具体的配置项
const isZenMode = computed(() => localConfig.value.isZenMode)
const openNodeRichText = computed(() => localConfig.value.openNodeRichText)
const isShowScrollbar = computed(() => localConfig.value.isShowScrollbar)
const enableDragImport = computed(() => localConfig.value.enableDragImport)
const useLeftKeySelectionRightKeyDrag = computed(() => localConfig.value.useLeftKeySelectionRightKeyDrag)

// 响应式数�?
const mindMapContainer = ref(null)
const mindMap = ref(null)
const mindMapData = ref({})
const mindMapConfig = ref({})
const showDragMask = ref(false)
const enableShowLoading = ref(false)
const storeConfigTimer = ref(null)

// 监听�?
watch(openNodeRichText, (newVal) => {
  if (newVal) {
    addRichTextPlugin()
  } else {
    removeRichTextPlugin()
  }
})

watch(isShowScrollbar, (newVal) => {
  if (newVal) {
    addScrollbarPlugin()
  } else {
    removeScrollbarPlugin()
  }
})

// 生命周期钩子
onMounted(async () => {
  await nextTick()
  showLoading()
  loadMindMapData()  // 这里改为调用重命名后的函数
  await nextTick()
  await init()
  hideLoading()
  // 事件监听
  $on('execCommand', execCommand)
  $on('paddingChange', onPaddingChange)
  $on('export', exportMap)
  $on('setData', setData)
  $on('startTextEdit', handleStartTextEdit)
  $on('endTextEdit', handleEndTextEdit)
  $on('createAssociativeLine', handleCreateLineFromActiveNode)
  $on('startPainter', handleStartPainter)
  $on('node_tree_render_end', handleHideLoading)
  $on('showLoading', handleShowLoading)
  $on('localStorageExceeded', onLocalStorageExceeded)
  $on('createFreeTextNode', handleCreateFreeTextNode) // 新增
  window.addEventListener('resize', handleResize)

})

onBeforeUnmount(() => {
  // 移除事件监听
  $off('execCommand', execCommand)
  $off('paddingChange', onPaddingChange)
  $off('export', exportMap)
  $off('setData', setData)
  $off('startTextEdit', handleStartTextEdit)
  $off('endTextEdit', handleEndTextEdit)
  $off('createAssociativeLine', handleCreateLineFromActiveNode)
  $off('startPainter', handleStartPainter)
  $off('node_tree_render_end', handleHideLoading)
  $off('showLoading', handleShowLoading)
  $off('localStorageExceeded', onLocalStorageExceeded)
   $off('createFreeTextNode', handleCreateFreeTextNode) // 新增
  window.removeEventListener('resize', handleResize)
  if (mindMap.value) {
    mindMap.value.destroy()
  }
})

// 存储自由文本框的数据
const freeTextBoxes = ref([])
let freeTextBoxCounter = 0

// 添加处理创建自由文本框的方法
const handleCreateFreeTextNode = () => {
  if (!mindMap.value) return
  
  // 创建独立的自由文本框
  createFreeTextBox()
}

// 更新文本元素内容，支持换行显示
const updateTextElementContent = (textElement, text) => {
  // 清除现有内容
  textElement.innerHTML = ''
  
  const lines = text.split('\n')
  const lineHeight = 1.4
  const fontSize = 14
  const maxCharsPerLine = 50 // 每行最大字符数，可根据需要调整
  
  let allLines = []
  
  // 处理每一行，如果超过最大字符数则自动换行
  lines.forEach(line => {
    if (line.length <= maxCharsPerLine) {
      allLines.push(line)
    } else {
      // 将长行分割成多行
      for (let i = 0; i < line.length; i += maxCharsPerLine) {
        allLines.push(line.substring(i, i + maxCharsPerLine))
      }
    }
  })
  
  // 计算垂直居中的起始位置
  const totalLines = allLines.length
  const totalHeight = (totalLines - 1) * fontSize * lineHeight
  const startY = -totalHeight / 2  // 从负的一半高度开始，实现垂直居中
  
  // 创建tspan元素显示每一行
  allLines.forEach((line, index) => {
    const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan')
    tspan.textContent = line || ' '  // 空行显示空格
    tspan.setAttribute('x', '0')
    
    // 第一行使用startY，后续行累加lineHeight
    if (index === 0) {
      tspan.setAttribute('dy', `${startY}px`)
    } else {
      tspan.setAttribute('dy', `${fontSize * lineHeight}px`)
    }
    
    textElement.appendChild(tspan)
  })
}

// 计算文本框尺寸的函数
const calculateTextBoxSize = (text) => {
  const lines = text.split('\n')
  const maxCharsPerLine = 50 // 与updateTextElementContent中的值保持一致
  
  let allLines = []
  let maxLineLength = 0
  
  // 处理每一行，计算自动换行后的总行数和最大行长度
  lines.forEach(line => {
    if (line.length <= maxCharsPerLine) {
      allLines.push(line)
      maxLineLength = Math.max(maxLineLength, line.length)
    } else {
      // 将长行分割成多行
      for (let i = 0; i < line.length; i += maxCharsPerLine) {
        const subLine = line.substring(i, i + maxCharsPerLine)
        allLines.push(subLine)
        maxLineLength = Math.max(maxLineLength, subLine.length)
      }
    }
  })
  
  const lineCount = Math.max(allLines.length, 1)
  maxLineLength = Math.max(maxLineLength, 5)
  
  const basePadding = 20
  const extraPadding = Math.min(maxLineLength * 1.5, 40)
  const totalPadding = basePadding + extraPadding
  
  // 计算宽度：基于最长行
  const baseWidth = 100
  const charWidth = 12
  const minWidth = 150
  const maxWidth = 400
  const calculatedWidth = baseWidth + (maxLineLength * charWidth) + (totalPadding * 2)
  const width = Math.max(minWidth, Math.min(maxWidth, calculatedWidth))
  
  // 计算高度：基于行数，减少内边距
  const fontSize = 14
  const lineHeight = 1.4
  const actualLineHeight = fontSize * lineHeight
  const minHeight = 36
  const verticalPadding = 16  // 减少垂直内边距
  const calculatedHeight = (lineCount * actualLineHeight) + verticalPadding
  const height = Math.max(minHeight, calculatedHeight)
  
  return {
    width,
    height,
    padding: totalPadding
  }
}

// 更新文本框尺寸的函数
const updateTextBoxSize = (textBoxGroup, text) => {
  const { width, height, padding } = calculateTextBoxSize(text)
  
  // 更新背景矩形
  const bgRect = textBoxGroup.querySelector('rect')
  bgRect.setAttribute('width', width)
  bgRect.setAttribute('height', height)
  bgRect.setAttribute('x', -width / 2)
  bgRect.setAttribute('y', -height / 2)
  
  // 更新删除按钮位置
  const deleteBtn = textBoxGroup.querySelector('circle')
  const deleteIcon = textBoxGroup.querySelector('text:last-child')
  const btnX = width / 2 - 15
  const btnY = -height / 2 + 15
  deleteBtn.setAttribute('cx', btnX)
  deleteBtn.setAttribute('cy', btnY)
  deleteIcon.setAttribute('x', btnX)
  deleteIcon.setAttribute('y', btnY + 4)
}

// 创建自由文本框函数
const createFreeTextBox = () => {
  // 通过容器获取SVG元素
  const svg = mindMapContainer.value.querySelector('svg')
  if (!svg) return
  
  // 生成唯一ID
  const textBoxId = `free-text-${++freeTextBoxCounter}`
  
  // 获取画布中心位置
  const svgRect = svg.getBoundingClientRect()
  const centerX = svgRect.width / 2
  const centerY = svgRect.height / 2
  
  // 创建文本框组
  const textBoxGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g')
  textBoxGroup.setAttribute('class', 'free-text-box')
  textBoxGroup.setAttribute('data-id', textBoxId)
  textBoxGroup.setAttribute('transform', `translate(${centerX}, ${centerY})`)
  
  const defaultText = '请输入内容'
  const { width, height, padding } = calculateTextBoxSize(defaultText)
  
  // 创建背景矩形 - 使用计算出的尺寸
  const bgRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
  bgRect.setAttribute('x', -width / 2)
  bgRect.setAttribute('y', -height / 2)
  bgRect.setAttribute('width', width)
  bgRect.setAttribute('height', height)
  bgRect.setAttribute('fill', '#f8f9fa')
  bgRect.setAttribute('stroke', '#549688')
  bgRect.setAttribute('stroke-width', '1.5')
  bgRect.setAttribute('rx', '8')  // 增加圆角
  bgRect.setAttribute('ry', '8')
  bgRect.style.cursor = 'move'
  bgRect.style.filter = 'drop-shadow(0 2px 4px rgba(84, 150, 136, 0.1))'
  
  // 创建文本元素
  const textElement = document.createElementNS('http://www.w3.org/2000/svg', 'text')
  textElement.setAttribute('x', '0')
  textElement.setAttribute('y', '2')
  textElement.setAttribute('text-anchor', 'middle')
  textElement.setAttribute('dominant-baseline', 'middle')
  textElement.setAttribute('fill', '#2c3e50')
  textElement.setAttribute('font-size', '14')
  textElement.setAttribute('font-family', '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif')
  textElement.setAttribute('font-weight', '500')
  textElement.style.cursor = 'text'
  textElement.style.userSelect = 'none'
  
  // 使用新的文本更新函数
  updateTextElementContent(textElement, defaultText)
  
  // 创建删除按钮 - 位置根据尺寸调整
  const deleteBtn = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
  const btnX = width / 2 - 15
  const btnY = -height / 2 + 15
  deleteBtn.setAttribute('cx', btnX)
  deleteBtn.setAttribute('cy', btnY)
  deleteBtn.setAttribute('r', '10')
  deleteBtn.setAttribute('fill', '#ff6b6b')
  deleteBtn.setAttribute('stroke', '#fff')
  deleteBtn.setAttribute('stroke-width', '2')
  deleteBtn.style.cursor = 'pointer'
  deleteBtn.style.opacity = '0'
  deleteBtn.style.transition = 'opacity 0.2s'
  
  const deleteIcon = document.createElementNS('http://www.w3.org/2000/svg', 'text')
  deleteIcon.setAttribute('x', btnX)
  deleteIcon.setAttribute('y', btnY + 4)
  deleteIcon.setAttribute('text-anchor', 'middle')
  deleteIcon.setAttribute('dominant-baseline', 'middle')
  deleteIcon.setAttribute('fill', '#fff')
  deleteIcon.setAttribute('font-size', '12')
  deleteIcon.setAttribute('font-family', 'Arial, sans-serif')
  deleteIcon.setAttribute('font-weight', 'bold')
  deleteIcon.style.cursor = 'pointer'
  deleteIcon.style.userSelect = 'none'
  deleteIcon.style.opacity = '0'
  deleteIcon.style.transition = 'opacity 0.2s'
  deleteIcon.textContent = '×'
  
  // 添加悬停效果的样式
  const addHoverEffects = () => {
    // 背景悬停效果
    bgRect.addEventListener('mouseenter', () => {
      bgRect.setAttribute('fill', '#e8f4f8')
      bgRect.setAttribute('stroke', '#4a9d8e')
      deleteBtn.style.opacity = '1'
      deleteIcon.style.opacity = '1'
    })
    bgRect.addEventListener('mouseleave', () => {
      bgRect.setAttribute('fill', '#f8f9fa')
      bgRect.setAttribute('stroke', '#e9ecef')
      deleteBtn.style.opacity = '0'
      deleteIcon.style.opacity = '0'
    })
  }
  
  // 组装元素
  textBoxGroup.appendChild(bgRect)
  textBoxGroup.appendChild(textElement)
  textBoxGroup.appendChild(deleteBtn)
  textBoxGroup.appendChild(deleteIcon)
  
  // 添加到SVG
  svg.appendChild(textBoxGroup)
  
  // 添加到存储集合
  freeTextBoxes.value.push(textBoxId)
  
  // 添加悬停效果
  addHoverEffects()
  
  // 添加事件监听器
  addFreeTextBoxEvents(textBoxGroup, textElement, textBoxId)
  
  // 立即进入编辑模式
  setTimeout(() => {
    startEditFreeTextBox(textElement)
  }, 100)
  
  // 保存数据
  setTimeout(() => {
    saveFreeTextBoxData()
  }, 200)
}

// 添加自由文本框事件
const addFreeTextBoxEvents = (group, textElement, textBoxId) => {
  let isDragging = false
  let startX, startY, startTransform
  let mouseMoveHandler, mouseUpHandler
  let hasMoved = false
  
  // 双击编辑
  textElement.addEventListener('dblclick', (e) => {
    e.stopPropagation()
    startEditFreeTextBox(textElement)
  })
  
  // 拖拽功能
  group.addEventListener('mousedown', (e) => {
    if (e.target === textElement) return // 点击文本时不拖拽
    
    isDragging = true
    hasMoved = false
    startX = e.clientX
    startY = e.clientY
    
    const transform = group.getAttribute('transform') || 'translate(0,0)'
    // 修复正则表达式
    const match = transform.match(/translate\(([^,]+),([^)]+)\)/)
    if (match) {
      startTransform = { x: parseFloat(match[1]), y: parseFloat(match[2]) }
    } else {
      startTransform = { x: 0, y: 0 }
    }
    
    // 创建鼠标移动处理函数
    mouseMoveHandler = (e) => {
      if (!isDragging) return
      
      const deltaX = e.clientX - startX
      const deltaY = e.clientY - startY
      
      // 只有当鼠标真正移动时才更新位置
      if (Math.abs(deltaX) > 3 || Math.abs(deltaY) > 3) {
        hasMoved = true
        const newX = startTransform.x + deltaX
        const newY = startTransform.y + deltaY
        
        group.setAttribute('transform', `translate(${newX}, ${newY})`)
      }
    }
    
    // 创建鼠标释放处理函数
    mouseUpHandler = (e) => {
      isDragging = false
      
      // 移除事件监听器
      document.removeEventListener('mousemove', mouseMoveHandler)
      document.removeEventListener('mouseup', mouseUpHandler)
    }
    
    // 添加事件监听器
    document.addEventListener('mousemove', mouseMoveHandler)
    document.addEventListener('mouseup', mouseUpHandler)
    
    e.preventDefault()
    e.stopPropagation()
  })
  
  // 删除功能
  const deleteBtn = group.querySelector('circle')
  const deleteIcon = group.querySelector('text:last-child')
  
  const handleDelete = (e) => {
    e.stopPropagation()
    group.remove()
    const index = freeTextBoxes.value.indexOf(textBoxId)
    if (index > -1) {
      freeTextBoxes.value.splice(index, 1)
    }
    saveFreeTextBoxData()
  }
  
  deleteBtn.addEventListener('click', handleDelete)
  deleteIcon.addEventListener('click', handleDelete)
}

// 开始编辑自由文本框
const startEditFreeTextBox = (textElement) => {
  const currentText = textElement.textContent
  
  // 获取文本框组
  const textBoxGroup = textElement.closest('.free-text-box')
  
  // 只隐藏文本元素，保留背景和删除按钮
  textElement.style.visibility = 'hidden'
  
  // 创建透明的textarea
  const textarea = document.createElement('textarea')
  textarea.value = currentText === '请输入内容' ? '' : currentText
  textarea.style.position = 'fixed'
  textarea.style.zIndex = '9999'
  textarea.style.fontSize = '14px'
  textarea.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
  textarea.style.fontWeight = '500'
  textarea.style.border = 'none'  // 移除边框
  textarea.style.outline = 'none'
  textarea.style.background = 'transparent'  // 透明背景
  textarea.style.textAlign = 'center'
  textarea.style.color = '#2c3e50'  // 透明文字，用户看不到输入
  textarea.style.padding = '8px 12px'
  textarea.style.margin = '0'
  textarea.style.borderRadius = '6px'
  textarea.style.resize = 'none'
  textarea.style.overflow = 'hidden'
  textarea.style.lineHeight = '1.4'
  textarea.style.minWidth = '150px'
  textarea.style.maxWidth = '400px'
  textarea.style.minHeight = '36px'
  textarea.style.caretColor = '#549688'  // 只显示光标
  
  // 获取背景矩形的位置和大小
  const bgRect = textBoxGroup.querySelector('rect')
  const bgWidth = parseFloat(bgRect.getAttribute('width'))
  const bgHeight = parseFloat(bgRect.getAttribute('height'))
  
  // 直接获取文本元素在屏幕上的位置
  const textRect = textElement.getBoundingClientRect()
  
  // 初始设置textarea大小
  const initialWidth = Math.max(150, bgWidth - 20)
  textarea.style.width = `${initialWidth}px`
  textarea.style.height = `${Math.max(36, bgHeight - 10)}px`
  
  // 计算textarea位置，使其居中对齐
  const textareaX = textRect.left + (textRect.width / 2) - (initialWidth / 2)
  const textareaY = textRect.top + (textRect.height / 2) - 18
  
  textarea.style.left = `${textareaX}px`
  textarea.style.top = `${textareaY}px`
  
  // 动态调整textarea和背景大小的函数
  const adjustTextareaSize = () => {
    const text = textarea.value
    const lines = text.split('\n')
    const maxCharsPerLine = 50 // 与其他函数保持一致
    
    // 处理自动换行，计算实际行数
    let allLines = []
    let maxLineLength = 0
    
    lines.forEach(line => {
      if (line.length <= maxCharsPerLine) {
        allLines.push(line)
        maxLineLength = Math.max(maxLineLength, line.length)
      } else {
        // 将长行分割成多行
        for (let i = 0; i < line.length; i += maxCharsPerLine) {
          const subLine = line.substring(i, i + maxCharsPerLine)
          allLines.push(subLine)
          maxLineLength = Math.max(maxLineLength, subLine.length)
        }
      }
    })
    
    const actualLineCount = Math.max(allLines.length, 1)
    
    // 计算宽度：基于最长行的字符数
    const charWidth = 12
    const padding = 24
    const newWidth = Math.min(400, Math.max(150, maxLineLength * charWidth + padding))
    
    // 计算高度：与节点高度计算保持一致
    const fontSize = 14
    const lineHeight = 1.4
    const actualLineHeight = fontSize * lineHeight
    const verticalPadding = 16
    const newHeight = Math.max(36, (actualLineCount * actualLineHeight) + verticalPadding)
    
    textarea.style.width = `${newWidth}px`
    textarea.style.height = `${newHeight}px`
    
    // 重新计算位置以保持居中
    const newTextareaX = textRect.left + (textRect.width / 2) - (newWidth / 2)
    const newTextareaY = textRect.top + (textRect.height / 2) - (newHeight / 2)
    
    textarea.style.left = `${newTextareaX}px`
    textarea.style.top = `${newTextareaY}px`
    
    // 同时更新背景矩形大小和显示的文本
    const { width: bgNewWidth, height: bgNewHeight } = calculateTextBoxSize(text || '请输入内容')
    bgRect.setAttribute('width', bgNewWidth)
    bgRect.setAttribute('height', bgNewHeight)
    bgRect.setAttribute('x', -bgNewWidth / 2)
    bgRect.setAttribute('y', -bgNewHeight / 2)
    
    // 实时更新文本元素显示内容（支持换行）
    updateTextElementContent(textElement, text || '请输入内容')
    
    // 更新删除按钮位置
    const deleteBtn = textBoxGroup.querySelector('circle')
    const deleteIcon = textBoxGroup.querySelector('text:last-child')
    const btnX = bgNewWidth / 2 - 15
    const btnY = -bgNewHeight / 2 + 15
    deleteBtn.setAttribute('cx', btnX)
    deleteBtn.setAttribute('cy', btnY)
    deleteIcon.setAttribute('x', btnX)
    deleteIcon.setAttribute('y', btnY + 4)
  }
  
  // 添加到页面
  document.body.appendChild(textarea)
  textarea.focus()
  textarea.select()
  
  // 初始调整大小
  adjustTextareaSize()
  
  // 监听输入事件，实时调整大小和显示内容
  textarea.addEventListener('input', adjustTextareaSize)
  
  // 监听键盘事件
  textarea.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      finishEdit()
    }
    if (e.key === 'Escape') {
      e.preventDefault()
      cancelEdit()
    }
  })
  
  // 完成编辑
  const finishEdit = () => {
    const newText = textarea.value.trim() || '请输入内容'
    
    // 更新文本元素内容（支持换行）
    updateTextElementContent(textElement, newText)
    
    // 显示文本元素
    textElement.style.visibility = 'visible'
    
    // 根据新文本更新文本框尺寸
    updateTextBoxSize(textBoxGroup, newText)
    
    document.body.removeChild(textarea)
    
    // 保存数据
    saveFreeTextBoxData()
  }
  
  // 取消编辑
  const cancelEdit = () => {
    textElement.style.visibility = 'visible'
    document.body.removeChild(textarea)
  }
  
  // 失去焦点时完成编辑
  textarea.addEventListener('blur', finishEdit)
}



// 保存自由节点数据
const saveFreeTextBoxData = () => {
  const freeTextBoxData = []
  const svg = mindMapContainer.value?.querySelector('svg')
  if (!svg) return
  
  const freeTextBoxGroups = svg.querySelectorAll('.free-text-box')
  freeTextBoxGroups.forEach(group => {
    const textElement = group.querySelector('text')
    const bgRect = group.querySelector('rect')
    const transform = group.getAttribute('transform')
    
    if (textElement && bgRect && transform) {
      // 提取位置信息
      const transformMatch = transform.match(/translate\(([^,]+),([^)]+)\)/)
      if (transformMatch) {
        const x = parseFloat(transformMatch[1])
        const y = parseFloat(transformMatch[2])
        
        // 获取文本内容
        let textContent = ''
        const tspans = textElement.querySelectorAll('tspan')
        if (tspans.length > 0) {
          textContent = Array.from(tspans).map(tspan => tspan.textContent).join('\n')
        } else {
          textContent = textElement.textContent
        }
        
        freeTextBoxData.push({
          id: group.getAttribute('data-id'),
          text: textContent,
          x: x,
          y: y,
          width: parseFloat(bgRect.getAttribute('width')),
          height: parseFloat(bgRect.getAttribute('height'))
        })
      }
    }
  })
  
  freeTextBoxes.value = freeTextBoxData
  
  // 保存到localStorage或其他存储
  const currentData = getApiData()
  const updatedData = {
    ...currentData,
    freeTextBoxes: freeTextBoxData
  }
  console.log(freeTextBoxData,"freeTextBoxData");
  
  storeData(updatedData)
}

// 恢复自由节点数据
const restoreFreeTextBoxes = () => {
  const data = getApiData()
  console.log('恢复自由节点数据:', data)
  
  if (data && data.freeTextBoxes && Array.isArray(data.freeTextBoxes) && data.freeTextBoxes.length > 0) {
    const svg = mindMapContainer.value?.querySelector('svg')
    if (!svg) {
      console.log('SVG容器未找到，延迟重试')
      setTimeout(() => {
        restoreFreeTextBoxes()
      }, 200)
      return
    }
    
    console.log('开始恢复', data.freeTextBoxes.length, '个自由节点')
    data.freeTextBoxes.forEach(boxData => {
      createFreeTextBoxFromData(boxData)
    })
    
    freeTextBoxes.value = data.freeTextBoxes
    console.log('自由节点恢复完成')
  } else {
    console.log('没有找到自由节点数据或数据为空')
  }
}

// 根据数据创建自由文本框
const createFreeTextBoxFromData = (boxData) => {
  const svg = mindMapContainer.value?.querySelector('svg')
  if (!svg) return
  
  const { width, height } = calculateTextBoxSize(boxData.text)
  
  // 创建文本框组
  const textBoxGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g')
  textBoxGroup.setAttribute('class', 'free-text-box')
  textBoxGroup.setAttribute('data-id', boxData.id)
  textBoxGroup.setAttribute('transform', `translate(${boxData.x}, ${boxData.y})`)
  
  // 创建背景矩形
  const bgRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
  bgRect.setAttribute('width', width)
  bgRect.setAttribute('height', height)
  bgRect.setAttribute('x', -width / 2)
  bgRect.setAttribute('y', -height / 2)
  bgRect.setAttribute('fill', '#f8f9fa')
  bgRect.setAttribute('stroke', '#e9ecef')
  bgRect.setAttribute('stroke-width', '1')
  bgRect.setAttribute('rx', '6')
  bgRect.setAttribute('ry', '6')
  bgRect.style.cursor = 'move'
  
  // 创建文本元素
  const textElement = document.createElementNS('http://www.w3.org/2000/svg', 'text')
  textElement.setAttribute('x', '0')
  textElement.setAttribute('y', '2')
  textElement.setAttribute('text-anchor', 'middle')
  textElement.setAttribute('dominant-baseline', 'middle')
  textElement.setAttribute('fill', '#2c3e50')
  textElement.setAttribute('font-size', '14')
  textElement.setAttribute('font-family', '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif')
  textElement.setAttribute('font-weight', '500')
  textElement.style.cursor = 'text'
  textElement.style.userSelect = 'none'
  
  // 设置文本内容
  updateTextElementContent(textElement, boxData.text)
  
  // 创建删除按钮
  const deleteBtn = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
  const btnX = width / 2 - 15
  const btnY = -height / 2 + 15
  deleteBtn.setAttribute('cx', btnX)
  deleteBtn.setAttribute('cy', btnY)
  deleteBtn.setAttribute('r', '10')
  deleteBtn.setAttribute('fill', '#ff6b6b')
  deleteBtn.setAttribute('stroke', '#ffffff')
  deleteBtn.setAttribute('stroke-width', '2')
  deleteBtn.style.cursor = 'pointer'
  deleteBtn.style.filter = 'drop-shadow(0 1px 3px rgba(0, 0, 0, 0.2))'
  
  // 创建删除图标
  const deleteIcon = document.createElementNS('http://www.w3.org/2000/svg', 'text')
  deleteIcon.setAttribute('x', btnX)
  deleteIcon.setAttribute('y', btnY + 4)
  deleteIcon.setAttribute('text-anchor', 'middle')
  deleteIcon.setAttribute('dominant-baseline', 'middle')
  deleteIcon.setAttribute('fill', '#ffffff')
  deleteIcon.setAttribute('font-size', '12')
  deleteIcon.setAttribute('font-family', 'Arial, sans-serif')
  deleteIcon.setAttribute('font-weight', 'bold')
  deleteIcon.style.cursor = 'pointer'
  deleteIcon.style.userSelect = 'none'
  deleteIcon.textContent = '×'
  
  // 组装元素
  textBoxGroup.appendChild(bgRect)
  textBoxGroup.appendChild(textElement)
  textBoxGroup.appendChild(deleteBtn)
  textBoxGroup.appendChild(deleteIcon)
  
  // 添加悬停效果
  const addHoverEffects = () => {
    bgRect.addEventListener('mouseenter', () => {
      bgRect.setAttribute('fill', '#e8f4f8')
      bgRect.setAttribute('stroke', '#4a9d8e')
    })
    bgRect.addEventListener('mouseleave', () => {
      bgRect.setAttribute('fill', '#f8f9fa')
      bgRect.setAttribute('stroke', '#549688')
    })
    
    deleteBtn.addEventListener('mouseenter', () => {
      deleteBtn.setAttribute('fill', '#ff5252')
      deleteBtn.setAttribute('r', '11')
    })
    deleteBtn.addEventListener('mouseleave', () => {
      deleteBtn.setAttribute('fill', '#ff6b6b')
      deleteBtn.setAttribute('r', '10')
    })
    
    const handleDelete = (e) => {
      e.stopPropagation()
      textBoxGroup.remove()
      const index = freeTextBoxes.value.findIndex(box => box.id === boxData.id)
      if (index > -1) {
        freeTextBoxes.value.splice(index, 1)
      }
      saveFreeTextBoxData()
    }
    
    deleteBtn.addEventListener('click', handleDelete)
    deleteIcon.addEventListener('click', handleDelete)
    
    textElement.addEventListener('dblclick', (e) => {
      e.stopPropagation()
      startEditFreeTextBox(textElement)
    })
  }
  
  addHoverEffects()
  
  // 添加事件
  addFreeTextBoxEvents(textBoxGroup, textElement, boxData.id)
  
  svg.appendChild(textBoxGroup)
}

// 方法
const onLocalStorageExceeded = () => {
  // ElNotification({
  //   type: 'warning',
  //   title: t('edit.tip'),
  //   message: t('edit.localStorageExceededTip'),
  //   duration: 0
  // })
}

const handleStartTextEdit = () => {
  mindMap.value.renderer.startTextEdit()
}

const handleEndTextEdit = () => {
  mindMap.value.renderer.endTextEdit()
}

const handleCreateLineFromActiveNode = () => {
  mindMap.value.associativeLine.createLineFromActiveNode()
}

const handleStartPainter = () => {
  mindMap.value.painter.startPainter()
}

const handleResize = () => {
  mindMap.value.resize()
}

const handleShowLoading = () => {
  enableShowLoading.value = true
  showLoading()
}

const handleHideLoading = () => {
  if (enableShowLoading.value) {
    enableShowLoading.value = false
    hideLoading()
  }
}

// 在组件顶部添加状态管理
const monitoredNodes = ref(new Set()) // 存储已监控的节点
const markedNodes = ref(new Set()) // 存储已标记的节点

// 创建状态tag的函数
// 修改createStatusTag函数，设置不同的显示位置
const createStatusTag = (nodeEl, text, position) => {
  const bbox = nodeEl.getBBox()
  
  // 创建tag组
  const tagGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g')
  tagGroup.setAttribute('class', `status-tag-${text}`)
  
  // 根据position设置不同的位置
  let offsetX, offsetY
  if (position === 'monitor') {
    // 已监控：显示在右上角
    offsetX = bbox.width - 75
    offsetY = 8
  } else {
    offsetX = bbox.width - 40
    offsetY = 8
  }
  
  tagGroup.setAttribute('transform', `translate(${offsetX}, ${offsetY})`)
  
  // 创建背景矩形
  const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
  rect.setAttribute('x', '-15')
  rect.setAttribute('y', '-8')
  rect.setAttribute('width', '30')
  rect.setAttribute('height', '16')
  rect.setAttribute('rx', '8')
  rect.setAttribute('fill', 'transparent')
  rect.setAttribute('opacity', '0.9')
  
  // 创建文本
  const tagText = document.createElementNS('http://www.w3.org/2000/svg', 'text')
  tagText.setAttribute('x', '0')
  tagText.setAttribute('y', '2')
  tagText.setAttribute('text-anchor', 'middle')
  tagText.setAttribute('dominant-baseline', 'middle')
  tagText.setAttribute('fill', '#1890ff')
  tagText.setAttribute('font-size', '10')
  tagText.setAttribute('font-family', 'Arial, sans-serif')
  tagText.textContent = text
  
  tagGroup.appendChild(rect)
  tagGroup.appendChild(tagText)
  
  return tagGroup
}

const getData = () => {
  mindMapData.value = getApiData()
  mindMapConfig.value = getConfig() || {}
  
  // 恢复监控和标记状态
  restoreNodeStatus(mindMapData.value)
}

// 修改manualSave函数，保存监控和标记状态
const manualSave = () => {
  const data = mindMap.value.getData(true)
  
  // 将监控和标记状态保存到数据中
  const saveDataWithStatus = {
    ...data,
    monitoredNodes: Array.from(monitoredNodes.value),
    markedNodes: Array.from(markedNodes.value)
  }
  
  storeData(saveDataWithStatus)
}

// 添加从数据中恢复状态的函数
const restoreNodeStatus = (data) => {
  if (data.monitoredNodes) {
    monitoredNodes.value = new Set(data.monitoredNodes)
  }
  if (data.markedNodes) {
    markedNodes.value = new Set(data.markedNodes)
  }
}

// 修改getData函数，加载时恢复状态
const loadMindMapData = () => {
  mindMapData.value = getApiData()
  mindMapConfig.value = getConfig() || {}
  
  // 恢复监控和标记状态
  restoreNodeStatus(mindMapData.value)
  
  // 在数据加载完成后，延迟恢复自由节点
  nextTick(() => {
    setTimeout(() => {
      restoreFreeTextBoxes()
    }, 100)
  })
}

// 修改bindSaveEvent函数，在数据变化时也保存状态
const bindSaveEvent = () => {
  $on('data_change', (data) => {
    const saveDataWithStatus = {
      root: data,
      monitoredNodes: Array.from(monitoredNodes.value),
      markedNodes: Array.from(markedNodes.value)
    }
    storeData(saveDataWithStatus)
  })
  $on('view_data_change', (data) => {
    clearTimeout(storeConfigTimer.value)
    storeConfigTimer.value = setTimeout(() => {
      storeData({
        view: data,
        monitoredNodes: Array.from(monitoredNodes.value),
        markedNodes: Array.from(markedNodes.value)
      })
    }, 300)
  })
}

// 修改updateNodeStatusTags函数，确保在节点渲染后正确显示状态
const updateNodeStatusTags = (nodeEl, nodeId) => {
  // 移除现有的状态tag
  const existingTags = nodeEl.querySelectorAll('.status-tag-已监控, .status-tag-已标记')
  existingTags.forEach(tag => tag.remove())
  
  // 添加监控tag
  if (monitoredNodes.value.has(nodeId)) {
    const monitorTag = createStatusTag(nodeEl, '已监控', 'monitor')
    nodeEl.appendChild(monitorTag)
  }
  
  // 添加标记tag
  if (markedNodes.value.has(nodeId)) {
    const markTag = createStatusTag(nodeEl, '已标记', 'mark')
    nodeEl.appendChild(markTag)
  }
}

// 修改addMonitorLabelsToNodes函数中的点击事件，添加自动保存
// 删除第347-375行的独立事件监听器代码，将其移到addMonitorLabelsToNodes函数内部

// 重新定义完整的addMonitorLabelsToNodes函数
const addMonitorLabelsToNodes = () => {
  // 获取所有节点元素
  const nodeElements = document.querySelectorAll('.smm-node')
  
  nodeElements.forEach((nodeEl, index) => {
    // 检查是否已经添加过监控标记，避免重复添加
    if (nodeEl.querySelector('.monitor-labels')) {
      return
    }
    
    // 获取节点ID（用于状态管理）
    const nodeId = nodeEl.getAttribute('data-uid') || `node-${index}`
    
    // 获取节点的边界框信息
    const bbox = nodeEl.getBBox()
    
    // 创建 SVG 监控标记组
    const monitorGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g')
    monitorGroup.setAttribute('class', 'monitor-labels')
    // 将监控标记放在节点上方中央位置
    monitorGroup.setAttribute('transform', `translate(${bbox.width / 2}, -25)`)
    
    // 创建第一个监控标记（只有文本，无背景）
    const text1 = document.createElementNS('http://www.w3.org/2000/svg', 'text')
    text1.setAttribute('class', 'monitor-label monitor-label-1')
    text1.setAttribute('x', '-15')
    text1.setAttribute('y', '20')
    text1.setAttribute('text-anchor', 'start')
    text1.setAttribute('dominant-baseline', 'auto')
    text1.setAttribute('fill', '#1890ff')
    text1.setAttribute('font-size', '12')
    text1.setAttribute('font-family', 'Arial, sans-serif')
    text1.style.cursor = 'pointer'
    text1.style.userSelect = 'none'
    text1.textContent = '监控'
    
    // 创建第二个监控标记（只有文本，无背景）
    const text2 = document.createElementNS('http://www.w3.org/2000/svg', 'text')
    text2.setAttribute('class', 'monitor-label monitor-label-2')
    text2.setAttribute('x', '15')
    text2.setAttribute('y', '20')
    text2.setAttribute('text-anchor', 'start')
    text2.setAttribute('dominant-baseline', 'auto')
    text2.setAttribute('fill', '#1890ff')
    text2.setAttribute('font-size', '12')
    text2.setAttribute('font-family', 'Arial, sans-serif')
    text2.style.cursor = 'pointer'
    text2.style.userSelect = 'none'
    text2.textContent = '标记'
    
    // 添加点击事件 - 监控
    text1.addEventListener('click', (e) => {
      e.stopPropagation()
      
      // 切换监控状态
      if (monitoredNodes.value.has(nodeId)) {
        monitoredNodes.value.delete(nodeId)
        // ElMessage.success('取消监控')
      } else {
        monitoredNodes.value.add(nodeId)
        // ElMessage.success('已添加监控')
      }
      
      // 更新状态tag
      updateNodeStatusTags(nodeEl, nodeId)
      
      // 自动保存状态
      manualSave()
    })
    
    // 添加点击事件 - 标记
    text2.addEventListener('click', (e) => {
      e.stopPropagation()
      
      // 切换标记状态
      if (markedNodes.value.has(nodeId)) {
        markedNodes.value.delete(nodeId)
        // ElMessage.success('取消标记')
      } else {
        markedNodes.value.add(nodeId)
        // ElMessage.success('已添加标记')
      }
      
      // 更新状态tag
      updateNodeStatusTags(nodeEl, nodeId)
      
      
      // 自动保存状态
      manualSave()
    })
    

    
    // 将文本元素添加到监控组
    monitorGroup.appendChild(text1)
    monitorGroup.appendChild(text2)
    
    // 将监控组添加到节点元素
    nodeEl.appendChild(monitorGroup)
    
    // 初始化状态tag（如果节点已经被监控或标记）
    updateNodeStatusTags(nodeEl, nodeId)
  })
}

const init = async () => {
  // let hasFileURL = hasFileURLCheck()
  let { root, layout, theme, view } = mindMapData.value
  const config = mindMapConfig.value

  // if (hasFileURL) {
  //   root = {
  //     data: {
  //       text: t('edit.root')
  //     },
  //     children: []
  //   }
  //   layout = exampleData.layout
  //   theme = exampleData.theme
  //   view = null
  // }
  let themeLocal = theme
  if(Object.keys(themeLocal.config).length === 0){
    // 设置三级及以下节点的间距和边框
    themeLocal.config ={
      node:{
        marginX: 50,
        marginY: 40,
        // 添加边框设置
        borderColor: '#549688',
        borderWidth: 1,
        borderRadius: 5,
        borderDasharray: 'none',
        paddingX:25,
        paddingY:15
      },
      second: {      // 二级节点配置
        // marginX: 100,  // 水平间距，默认值
        // marginY: 50    // 垂直间距，默认值
        paddingX:25,
        paddingY:15
      },
      root:{
        paddingX:30,
        paddingY:15
      }
    } 
  }
  mindMap.value = new MindMap({
    el: mindMapContainer.value,
    data: root,
    fit: false,
    layout: layout,
    theme: theme.template,
    themeConfig: {...themeLocal.config,},
    viewData: view,
    nodeTextEditZIndex: 1000,
    nodeNoteTooltipZIndex: 1000,
    
    customNoteContentShow: {
      show: (content, left, top, node) => {
        $emit('showNoteContent', content, left, top, node)
      },
      hide: () => {
        // $emit('hideNoteContent')
      }
    },
    openRealtimeRenderOnNodeTextEdit: true,
    enableAutoEnterTextEditWhenKeydown: true,
    demonstrateConfig: {
      openBlankMode: false
    },
    ...(config || {}),
    iconList: [...icon],
    useLeftKeySelectionRightKeyDrag: useLeftKeySelectionRightKeyDrag.value,
    customInnerElsAppendTo: null,
    customHandleClipboardText: handleClipboardText,
    defaultNodeImage: import('../../../assets/img/图片加载失败.svg'),
    initRootNodePosition: ['center', 'center'],
    handleIsSplitByWrapOnPasteCreateNewNode: () => {
      return ElMessageBox.confirm(
        t('edit.splitByWrap'),
        t('edit.tip'),
        {
          confirmButtonText: t('edit.yes'),
          cancelButtonText: t('edit.no'),
          type: 'warning'
        }
      )
    },
    errorHandler: (code, err) => {
      console.error(err)
      switch (code) {
        case 'export_error':
          ElMessage.error(t('edit.exportError'))
          break
        default:
          break
      }
    },
    addContentToFooter: () => {
      const text = extraTextOnExport.value.trim()
      if (!text) return null
      const el = document.createElement('div')
      el.className = 'footer'
      el.innerHTML = text
      const cssText = `
        .footer {
          width: 100%;
          height: 30px;
          display: flex;
          justify-content: center;
          align-items: center;
          font-size: 12px;
          color: #979797;
        }
      `
      return {
        el,
        cssText,
        height: 30
      }
    },
    expandBtnNumHandler: num => {
      return num >= 100 ? '' : num
    },
    beforeDeleteNodeImg: node => {
      return new Promise(resolve => {
        ElMessageBox.confirm(
          t('edit.deleteNodeImgTip'),
          t('edit.tip'),
          {
            confirmButtonText: t('edit.yes'),
            cancelButtonText: t('edit.no'),
            type: 'warning'
          }
        )
          .then(() => {
            resolve(false)
          })
          .catch(() => {
            resolve(true)
          })
      })
    }
  })
  mindMap.value.on('node_tree_render_end', () => {
     nextTick(() => {
      addMonitorLabelsToNodes()
      // 如果还没有恢复过自由节点，再次尝试恢复
      if (freeTextBoxes.value.length === 0) {
        setTimeout(() => {
          restoreFreeTextBoxes()
        }, 500)
      }
    })
  })
  console.log(mindMap.value.themeConfig,"ficici")
  await loadPlugins()
  mindMap.value.keyCommand.addShortcut('Control+s', () => {
    manualSave()
  })
  
  // 转发事件
  ;[
    'node_active',
    'data_change',
    'view_data_change',
    'back_forward',
    'node_contextmenu',
    'node_click',
    'draw_click',
    'expand_btn_click',
    'svg_mousedown',
    'mouseup',
    'mode_change',
    'node_tree_render_end',
    'rich_text_selection_change',
    'transforming-dom-to-images',
    'generalization_node_contextmenu',
    'painter_start',
    'painter_end',
    'scrollbar_change',
    'scale',
    'translate',
    'node_attachmentClick',
    'node_attachmentContextmenu',
    'demonstrate_jump',
    'exit_demonstrate',
    'node_note_dblclick',
    'node_mousedown'
  ].forEach(event => {
    mindMap.value.on(event, (...args) => {
      $emit(event, ...args)
    })
  })
  
  bindSaveEvent()
  
  // 监听数据变化，自动保存自由节点
  mindMap.value.on('data_change', () => {
    setTimeout(() => {
      saveFreeTextBoxData()
    }, 100)
  })
  
  if (window.takeOverApp) {
    $emit('app_inited', mindMap.value)
  }
  
  // if (hasFileURL) {
  //   $emit('handle_file_url')
  // }
  
  // api/index.js文件使用
  window.getCurrentData = () => {
    const fullData = mindMap.value.getData(true)
    return { ...fullData }
  }
  
  // cooperateTest()
}

const loadPlugins = async () => {
  // 动态导入所有插件，避免构造函数问题
  const [
    { default: PainterPlugin },
    { default: MiniMapPlugin },
    { default: WatermarkPlugin },
    { default: DragPlugin },
    { default: KeyboardNavigationPlugin },
    { default: ExportPDFPlugin },
    { default: ExportPlugin },
    { default: SelectPlugin },
    { default: AssociativeLinePlugin },
    { default: NodeImgAdjustPlugin },
    { default: TouchEventPlugin },
    { default: SearchPluginModule },
    { default: FormulaPlugin },
    { default: RainbowLinesPlugin },
    { default: DemonstratePlugin },
    { default: OuterFramePlugin },
    { default: MindMapLayoutProPlugin },
    { default: NodeBase64ImageStoragePlugin },
    // ThemesPluginModule
  ] = await Promise.all([
    import('simple-mind-map/src/plugins/Painter.js'),
    import('simple-mind-map/src/plugins/MiniMap.js'),
    import('simple-mind-map/src/plugins/Watermark.js'),
    import('simple-mind-map/src/plugins/Drag.js'),
    import('simple-mind-map/src/plugins/KeyboardNavigation.js'),
    import('simple-mind-map/src/plugins/ExportPDF.js'),
    import('simple-mind-map/src/plugins/Export.js'),
    import('simple-mind-map/src/plugins/Select.js'),
    import('simple-mind-map/src/plugins/AssociativeLine.js'),
    import('simple-mind-map/src/plugins/NodeImgAdjust.js'),
    import('simple-mind-map/src/plugins/TouchEvent.js'),
    import('simple-mind-map/src/plugins/Search.js'),
    import('simple-mind-map/src/plugins/Formula.js'),
    import('simple-mind-map/src/plugins/RainbowLines.js'),
    import('simple-mind-map/src/plugins/Demonstrate.js'),
    import('simple-mind-map/src/plugins/OuterFrame.js'),
    import('simple-mind-map/src/plugins/MindMapLayoutPro.js'),
    import('simple-mind-map/src/plugins/NodeBase64ImageStorage.js'),
    // import('simple-mind-map-plugin-themes')
  ])

  // 获取 ThemesPlugin，可能是默认导出或命名导出
  // const ThemesPlugin = ThemesPluginModule.default || ThemesPluginModule

  // 安全地添加插件，检查是否为构造函数
  const addPluginSafely = (plugin, name) => {
    if (typeof plugin === 'function') {
      try {
        mindMap.value.addPlugin(plugin)
      } catch (error) {
        console.error(`Failed to add plugin ${name}:`, error)
      }
    } else {
      console.warn(`Plugin ${name} is not a constructor:`, plugin)
    }
  }

  addPluginSafely(PainterPlugin, 'PainterPlugin')
  addPluginSafely(MiniMapPlugin, 'MiniMapPlugin')
  addPluginSafely(WatermarkPlugin, 'WatermarkPlugin')
  addPluginSafely(DragPlugin, 'DragPlugin')
  addPluginSafely(KeyboardNavigationPlugin, 'KeyboardNavigationPlugin')
  addPluginSafely(ExportPDFPlugin, 'ExportPDFPlugin')
  addPluginSafely(ExportPlugin, 'ExportPlugin')
  addPluginSafely(SelectPlugin, 'SelectPlugin')
  addPluginSafely(AssociativeLinePlugin, 'AssociativeLinePlugin')
  addPluginSafely(NodeImgAdjustPlugin, 'NodeImgAdjustPlugin')
  addPluginSafely(TouchEventPlugin, 'TouchEventPlugin')
  addPluginSafely(SearchPluginModule, 'SearchPluginModule')
  addPluginSafely(FormulaPlugin, 'FormulaPlugin')
  addPluginSafely(RainbowLinesPlugin, 'RainbowLinesPlugin')
  addPluginSafely(DemonstratePlugin, 'DemonstratePlugin')
  addPluginSafely(OuterFramePlugin, 'OuterFramePlugin')
  addPluginSafely(MindMapLayoutProPlugin, 'MindMapLayoutProPlugin')
  addPluginSafely(NodeBase64ImageStoragePlugin, 'NodeBase64ImageStoragePlugin')
  // addPluginSafely(ThemesPlugin, 'ThemesPlugin')
  
  if (openNodeRichText.value) addRichTextPlugin()
  if (isShowScrollbar.value) addScrollbarPlugin()
}

// const hasFileURLCheck = () => {
//   const fileURL = route.query.fileURL
//   if (!fileURL) return false
//   return /\.(smm|json|xmind|md|xlsx)$/.test(fileURL)
// }

const setData = (data) => {
  handleShowLoading()
  let rootNodeData = null
  if (data.root) {
    mindMap.value.setFullData(data)
    rootNodeData = data.root
  } else {
    mindMap.value.setData(data)
    rootNodeData = data
  }
  mindMap.value.view.reset()
  manualSave()
  
  if (rootNodeData.data.richText && !openNodeRichText.value) {
    $emit('toggleOpenNodeRichText', true)
    ElNotification.info({
      title: t('edit.tip'),
      message: t('edit.autoOpenNodeRichTextTip')
    })
  }
}

const reRender = () => {
  mindMap.value.reRender()
}

const execCommand = (...args) => {
  mindMap.value.execCommand(...args)
}

const exportMap = async (...args) => {
  try {
    showLoading()
    
    const exportType = args[0]
    
    // 在导出前，将自由节点数据添加到思维导图数据中
    if (['smm', 'json'].includes(exportType)) {
      // 获取当前思维导图数据
      const currentData = mindMap.value.getData(true)
      
      // 获取自由节点数据
      const freeTextBoxData = []
      const svg = mindMapContainer.value?.querySelector('svg')
      if (svg) {
        const freeTextBoxGroups = svg.querySelectorAll('.free-text-box')
        freeTextBoxGroups.forEach(group => {
          const textElement = group.querySelector('text')
          const bgRect = group.querySelector('rect')
          const transform = group.getAttribute('transform')
          
          if (textElement && bgRect && transform) {
            // 提取位置信息
            const transformMatch = transform.match(/translate\(([^,]+),([^)]+)\)/)
            if (transformMatch) {
              const x = parseFloat(transformMatch[1])
              const y = parseFloat(transformMatch[2])
              
              // 获取文本内容，确保是字符串格式
              let text = ''
              const tspans = textElement.querySelectorAll('tspan')
              if (tspans.length > 0) {  
                text = Array.from(tspans).map(tspan => (tspan.textContent || '')).join('\n')
              } else {
                text = textElement.textContent || ''
              }
              
              // 确保所有值都是有效的
              freeTextBoxData.push({
                id: group.getAttribute('data-id') || `free-text-${Date.now()}-${Math.random()}`,
                x: isNaN(x) ? 0 : x,
                y: isNaN(y) ? 0 : y,
                text: String(text), // 确保文本是字符串
                width: parseFloat(bgRect.getAttribute('width')) || 100,
                height: parseFloat(bgRect.getAttribute('height')) || 50
              })
            }
          }
        })
      }
      
      // 创建导出数据，不直接修改思维导图数据
      const exportData = {
        ...currentData,
        freeTextBoxes: freeTextBoxData
      }
      
      // 对于JSON和SMM格式，直接导出包含自由节点的数据
      if (exportType === 'json') {
        // 直接下载JSON文件，避免通过setData触发富文本处理
        const jsonStr = JSON.stringify(exportData, null, 2)
        const blob = new Blob([jsonStr], { type: 'application/json' })
        const url = URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = `${args[2] || 'mindmap'}.json`
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        URL.revokeObjectURL(url)
        
        hideLoading()
        return
      } else if (exportType === 'smm') {
        // 对于SMM格式，也直接处理
        const smmStr = JSON.stringify(exportData)
        const blob = new Blob([smmStr], { type: 'application/octet-stream' })
        const url = URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = `${args[2] || 'mindmap'}.smm`
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        URL.revokeObjectURL(url)
        
        hideLoading()
        return
      }
    }
    
    // 如果是 XMind 导出，动态加载 ExportXMind 插件
    if (exportType === 'xmind') {
      // 动态导入 ExportXMind 插件
      const { default: ExportXMind } = await import('simple-mind-map/src/plugins/ExportXMind.js')
      
      // 临时添加插件
      mindMap.value.addPlugin(ExportXMind)
      
      try {
        await mindMap.value.export(...args)
      } finally {
        // 导出完成后移除插件，避免内存泄漏
        mindMap.value.removePlugin(ExportXMind)
      }
    } else {
      await mindMap.value.export(...args)
    }
    
    hideLoading()
  } catch (error) {
    console.log(error)
    hideLoading()
  }
}

const onPaddingChange = (data) => {
  mindMap.value.updateConfig(data)
}

const addRichTextPlugin = () => {
  if (!mindMap.value) return
  mindMap.value.addPlugin(RichText)
}

const removeRichTextPlugin = () => {
  mindMap.value.removePlugin(RichText)
}

const addScrollbarPlugin = () => {
  if (!mindMap.value) return
  mindMap.value.addPlugin(ScrollbarPlugin)
}

const removeScrollbarPlugin = () => {
  mindMap.value.removePlugin(ScrollbarPlugin)
}

const cooperateTest = () => {
  if (mindMap.value.cooperate && route.query.userName) {
    mindMap.value.cooperate.setProvider(null, {
      roomName: 'demo-room',
      signalingList: ['ws://localhost:4444']
    })
    mindMap.value.cooperate.setUserInfo({
      id: Math.random(),
      name: route.query.userName,
      color: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#909399'][
        Math.floor(Math.random() * 5)
      ],
      avatar:
        Math.random() > 0.5
          ? 'https://img0.baidu.com/it/u=4270674549,2416627993&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1696006800&t=4d32871d14a7224a4591d0c3c7a97311'
          : ''
    })
  }
}

const onDragenter = () => {
  if (!enableDragImport.value || isDragOutlineTreeNode.value) return
  showDragMask.value = true
}

const onDragleave = () => {
  showDragMask.value = false
}

const onDrop = (e) => {
  if (!enableDragImport.value) return
  showDragMask.value = false
  const dt = e.dataTransfer
  const file = dt.files && dt.files[0]
  if (!file) return
  $emit('importFile', file)
}



// 暴露方法给父组件
defineExpose({
  reRender,
  execCommand,
  exportMap,
  setData,
  manualSave,
  mindMap  // 新增：暴露 mindMap 实例
})
</script>

<style lang="less" scoped>
.editContainer {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  overflow: hidden; // 添加这行
  width: 100vw;     // 添加这行
  height: 100vh;    // 添加这行

  .dragMask {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(255, 255, 255, 0.8);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3999;

    .dragTip {
      pointer-events: none;
      font-weight: bold;
    }
  }

  .mindMapContainer {
    position: absolute;
    left: 0px;
    top: 0px;
    width: 100%;
    height: 100%;
  }
}

// 增加三级子节点以上的间距
:deep(.smm-node) {
// 为三级及以上节点增加间距
&[data-level="2"] {
margin-bottom: 15px !important;
}

&[data-level="3"], 
&[data-level="4"], 
&[data-level="5"] {
margin-bottom: 20px !important;
}
}

// 监控标记样式优化
:deep(.monitor-labels) {
.monitor-label {
transition: all 0.2s ease;

&:hover {
transform: scale(1.1);
}
}
}
</style>
